﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace Core
{
    /// <summary>
    /// 静态上下文
    /// </summary>
    public static class Context
    {
        private static readonly Dictionary<string, GameContext> Dict = new();

        public static SystemContext Sys { get; private set; }
        public static GameContext Game { get; private set; }
        public static MonoBehaviour Mono { get; private set; }

        private static TblGame tblGame;
        private static ESysGame startupProject;

        public static void Awake(TblGame tbl, MonoBehaviour mono, ESysGame startup_project)
        {
            QualitySettings.vSyncCount = 1;
            Application.targetFrameRate = 30;
            Mono = mono;
            startupProject = startup_project;

            // Tips.Awake();

            tblGame = tbl;

            Dict.Clear();
        }

        public static void SetContext(Type type)
        {
            Sys = Activator.CreateInstance(typeof(SystemContext)) as SystemContext;
            Debug.Assert(Sys != null, nameof(Sys) + " != null");

            Sys.Awake(Mono);
            Sys.Assembly.Parse(type.Assembly);
            Sys.AddCoreComponent();

            AddGameContent();
        }

        private static void AddGameContent()
        {
            if (tblGame.Count == 0)
            {
                log.err("没有可以启动的游戏");
                return;
            }

            var gameTypes = Sys.Assembly.GetAttrTypes(typeof(IsGameAttribute));

            foreach (var t in gameTypes)
            {
                if (Activator.CreateInstance(t) is not GameContext game) continue;
                var gameName = game.ToString();

                var index1 = gameName.IndexOf("_", StringComparison.Ordinal);
                var index2 = gameName.IndexOf(".", StringComparison.Ordinal);
                gameName = gameName[(index1 + 1)..index2];

                var conf = tblGame.Find(gameName);

                if (conf == null) continue;
                if (conf.Id != (int)startupProject) continue;

                game.Awake(Mono, conf);
                game.AddCoreComponent();

                Dict[conf.Name] = game;
            }
        }

        public static void Start()
        {
            var conf = tblGame.Find((int)startupProject);
            var game = Dict[conf.Name];
            Game = game;
            Game.Enter();
            // Switch(conf.Name);
        }

        public static void Update()
        {
            Sys?.Factory.Update();
            Game?.Factory.Update();
        }

        public static void LateUpdate()
        {
            Sys?.Factory.LateUpdate();
            Game?.Factory.LateUpdate();
        }

        public static void FixedUpdate()
        {
            Sys?.Factory.FixedUpdate();
            Game?.Factory.FixedUpdate();
        }

        public static void Destroy()
        {
            Messenger.Post(GlobalEvent.OnDestroy);

            Sys.Dispose();
            Sys = null;

            Game = null;
            foreach (var pair in Dict)
            {
                pair.Value.Dispose();
            }

            Dict.Clear();

            // Tips.Dispose();

            ReferencePool.Clear();
        }

        public static bool Switch(string name = "")
        {
            // var variant = Sys.Variant.Pop(name);
            //
            // if (variant == null)
            // {
            //     Tips.ShowNormal($"当前没有更新的关卡了");
            //     return false;
            // }

            // var game = Dict[variant.GameName];
            // Game?.Exit();
            // Game = game;
            // if (Game != null)
            // {
            //     Game.SetVariant(variant);
            //     Game.Enter();
            // }

            return true;
        }

        public static void SwitchPrev()
        {
            var conf = tblGame.Find(0);
            if (Game == null)
            {
                Switch(conf.Name);
                return;
            }

            var idx = tblGame.IndexOf(Game.Conf);
            idx = (idx - 1 + tblGame.Count) % tblGame.Count;
            conf = tblGame.Find(idx);
            Switch(conf.Name);
        }

        public static void SwitchNext()
        {
            var conf = tblGame.Find(0);
            if (Game == null)
            {
                Switch(conf.Name);
                return;
            }

            var idx = tblGame.IndexOf(Game.Conf);
            idx = (idx + 1) % tblGame.Count;
            conf = tblGame.Find(idx);
            Switch(conf.Name);
        }
    }
}